<template>
  <div class="avatar">
    <!-- <button @click="initSDK()" class="fixed bottom-10 right-10 bg-blue-500 text-white px-4 py-2 rounded-md">实例化SDK</button> -->
    <el-container>
      <el-aside width="200px" height="840px">
        <el-row>
          <el-button style="margin: 0" @click="initSDK()" type="primary">实例化SDK</el-button>
          <el-button style="margin: 0" @click="createRecoder()" type="primary"
            >创建录音器</el-button
          >
          <el-button style="margin: 0" @click="setSDKEvenet()" type="primary"
            >设置SDK监听事件</el-button
          >
          <el-button style="margin: 0" @click="setPlayerEvenet()" type="primary"
            >设置播放器监听事件</el-button
          >
          <el-button style="margin: 0" @click="SetApiInfodialog = true" type="primary"
            >SetApiInfo</el-button
          >
          <el-button style="margin: 0" @click="SetGlobalParamsdialog = true" type="primary"
            >SetGlobalParams</el-button
          >
          <el-button style="margin: 0" @click="start()" type="primary">Start</el-button>
          <el-radio v-model="nlp" :label="true">开启语义理解</el-radio>
          <el-radio v-model="nlp" :label="false">关闭语义理解</el-radio>
          <el-input
            type="textarea"
            placeholder="请输入内容,包括符号在内，最大2000字符"
            v-model="textarea"
            maxlength="2000"
            show-word-limit
            :autosize="{ minRows: 5, maxRows: 10 }"
          >
          </el-input>
          <el-input v-model="vc" placeholder="变声"></el-input>
          <el-input v-model.number="emotion" placeholder="情感系数"></el-input>
          <el-button style="margin: 0" @click="writeText()" type="primary">文本驱动</el-button>
          <el-button style="margin: 0" @click="interrupt()" type="primary">打断</el-button>
          <el-input v-model="action" placeholder="执行动作"></el-input>
          <el-button style="margin: 0" @click="writeCmd()" type="primary">执行动作</el-button>
          <el-button
            style="margin: 0"
            @click="startRecord()"
            v-if="recorderbutton == false"
            type="primary"
            >开启录音</el-button
          >
          <el-button
            style="margin: 0"
            @click="stopRecord()"
            v-if="recorderbutton == true"
            type="primary"
            >关闭录音</el-button
          >
          <el-button style="margin: 0" @click="stop()" type="primary">关闭连接</el-button>
          <el-button style="margin: 0" @click="destroy()" type="primary">销毁SDK</el-button>
        </el-row>
      </el-aside>

      <el-main class="htmleaf-content" style="padding: 0">
        <div class="weather rain" id="wrapper"></div>
        <span>透明度</span
        ><input type="range" id="opacityRange" min="0" max="1" step="0.1" value="1" />

        <!-- 添加对话列表 -->
        <div class="chat-list">
          <div v-for="(msg, index) in chatList" :key="index" class="chat-item" :class="msg.type">
            <div class="chat-content">{{ msg.content }}</div>
            <div class="chat-time">{{ msg.time }}</div>
          </div>
        </div>
      </el-main>

      <!--SetApiInfo悬浮框-->
      <el-dialog title="初始化SDK" v-model="SetApiInfodialog">
        <el-form :model="form">
          <span>此处参数均去交互平台-接口服务中获取</span>
          <el-form-item label="Appid" :label-width="formLabelWidth">
            <el-input class="widthclass" v-model="form.appid" autocomplete="off"></el-input>
            <span>必填</span>
          </el-form-item>
          <el-form-item label="ApiKey" :label-width="formLabelWidth">
            <el-input class="widthclass" v-model="form.apikey" autocomplete="off"></el-input>
            <span>必填</span>
          </el-form-item>
          <el-form-item label="ApiSecret" :label-width="formLabelWidth">
            <el-input class="widthclass" v-model="form.apisecret" autocomplete="off"></el-input>
            <span>必填</span>
          </el-form-item>
          <el-form-item label="SceneId" :label-width="formLabelWidth">
            <el-input class="widthclass" v-model="form.sceneid" autocomplete="off"></el-input>
            <span>必填</span>
          </el-form-item>
          <el-form-item label="ServerUrl" :label-width="formLabelWidth">
            <el-input class="widthclass" v-model="form.serverurl" autocomplete="off"></el-input>
            <span>必填</span>
          </el-form-item>
        </el-form>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="SetApiInfodialog = false">取 消</el-button>
            <el-button type="primary" @click="((SetApiInfodialog = false), SetApiInfo2())"
              >确 定</el-button
            >
          </div>
        </template>
      </el-dialog>
      <!--SetGlobalParams悬浮框-->
      <el-dialog title="设置全局变量" v-model="SetGlobalParamsdialog">
        <div style="text-align: center"><h3>打断模式全局设置</h3></div>
        <el-form :model="setglobalparamsform" :label-width="formLabelWidth">
          <el-form-item label="视频协议">
            <el-tooltip
              class="item"
              effect="dark"
              content="支持webrtc/xrtc/rtmp(控制台打印视频流地址)"
              placement="right-start"
            >
              <i class="el-icon-question"></i>
            </el-tooltip>
            <el-select v-model="setglobalparamsform.stream.protocol" placeholder="请选择视频流协议">
              <el-option label="xrtc" value="xrtc"></el-option>
              <el-option label="webrtc" value="webrtc"></el-option>
              <el-option label="rtmp" value="rtmp"></el-option>
            </el-select>
            <span>必填</span>
          </el-form-item>
          <el-form-item label="透明背景">
            <el-tooltip class="item" effect="dark" content="仅支持xrtc协议" placement="right-start">
              <i class="el-icon-question"></i>
            </el-tooltip>
            <el-switch v-model="setglobalparamsform.stream.alpha"></el-switch>
          </el-form-item>
          <el-form-item label="全局交互模式">
            <el-radio-group v-model="setglobalparamsform.avatar_dispatch.interactive_mode">
              <el-radio :label="0">追加模式（信息依次播报）</el-radio>
              <el-radio :label="1">打断模式（直接播报最新）</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="形象ID">
            <el-input
              class="widthclass"
              v-model="setglobalparamsform.avatar.avatar_id"
              autocomplete="on"
              placeholder="到交互平台-接口服务-形象列表中获取id"
            ></el-input>
            <span>必填</span>
          </el-form-item>
          <el-form-item label="分辨率高">
            <el-input
              class="widthclass"
              v-model="setglobalparamsform.avatar.height"
              autocomplete="on"
            ></el-input>
          </el-form-item>
          <el-form-item label="分辨率宽">
            <el-input
              class="widthclass"
              v-model="setglobalparamsform.avatar.width"
              autocomplete="on"
            ></el-input>
          </el-form-item>
          <el-form-item label="音频采样率">
            <el-radio-group v-model="setglobalparamsform.avatar.audio_format">
              <el-radio :label="1">16K(传1)</el-radio>
              <el-radio :label="2">24K(传2，大部分情况默认24K即可)</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="形象裁剪" v-if="setglobalparamsform.avatar.mask_region != null">
            <el-input
              class="widthclass"
              v-model="setglobalparamsform.avatar.mask_region"
              autocomplete="on"
              placeholder="对形象进行裁剪[从左到右,从上到下,从右到左,从下到上]"
            ></el-input>
          </el-form-item>
          <el-form-item label="发音人">
            <el-input
              class="widthclass"
              v-model="setglobalparamsform.tts.vcn"
              autocomplete="on"
              placeholder="到交互平台-接口服务-声音列表中获取id"
            ></el-input>
            <span>必填</span>
          </el-form-item>
          <el-form-item label="情感">
            <el-input
              class="widthclass"
              v-model.number="setglobalparamsform.tts.emotion"
              autocomplete="on"
              placeholder="到交互平台-接口服务-声音列表中获取id"
            ></el-input>
          </el-form-item>
          <el-form-item label="是否开启字幕">
            <el-radio-group v-model="setglobalparamsform.subtitle.subtitle">
              <el-radio :label="1">开启</el-radio>
              <el-radio :label="0">关闭</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="字体颜色">
            <el-color-picker v-model="setglobalparamsform.subtitle.font_color"></el-color-picker>
          </el-form-item>
          <el-form-item label="是否开启背景图">
            <el-radio-group v-model="setglobalparamsform.enable">
              <el-radio :label="true">开启</el-radio>
              <el-radio :label="false">关闭</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="背景图片">
            <el-radio-group v-model="setglobalparamsform.background.type">
              <el-radio label="url">URL</el-radio>
              <el-radio label="res_key">res_key(到交互平台-素材管理中获取)</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="背景数据">
            <el-input v-model="setglobalparamsform.background.data" autocomplete="on"></el-input>
          </el-form-item>
        </el-form>

        <el-form :model="form"> </el-form>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="SetGlobalParamsdialog = false">取 消</el-button>
            <el-button type="primary" @click="((SetGlobalParamsdialog = false), SetGlobalParams())"
              >确 定</el-button
            >
          </div>
        </template>
      </el-dialog>
    </el-container>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
import AvatarPlatform, { PlayerEvents, SDKEvents } from './vm-sdk/avatar-sdk-web_3.1.1.1011'
import { checkAutoplayPermission } from '@/utils'

// 响应式状态
const SetApiInfodialog = ref(false)
const SetGlobalParamsdialog = ref(false)
const form = reactive({
  appid: '654fea56',
  apikey: '1283ac1e94838e94ef81e9d888e32d28',
  apisecret: 'YjVmODliNjAxMzg0ZDgwOWRlMjA2OGRh',
  sceneid: '188834725538959360',
  serverurl: 'wss://avatar.cn-huadong-1.xf-yun.com/v1/interact',
})

const setglobalparamsform = reactive({
  stream: {
    protocol: 'webrtc',
    fps: 25,
    bitrate: 1000000,
    alpha: false,
  },
  avatar: {
    avatar_id: '110117005',
    width: 1080,
    height: 1920,
    mask_region: '[0,0,1080,1920]',
    scale: 1,
    move_h: 0,
    move_v: 0,
    audio_format: 1,
  },
  tts: {
    vcn: 'x4_lingxiaoying_assist',
    speed: 50,
    pitch: 50,
    volume: 100,
    emotion: 13,
  },
  avatar_dispatch: {
    interactive_mode: 1,
  },
  subtitle: {
    subtitle: 1,
    font_color: '#FFFFFF',
    font_name: 'Sanji.Suxian.Simple',
    position_x: 100,
    position_y: 0,
    font_size: 10,
    width: 100,
    height: 100,
  },
  enable: false,
  background: {
    type: 'res_key',
    data: '22SLM2teIw+aqR6Xsm2JbH6Ng310kDam2NiCY/RQ9n6dw47gMO+7gGUJfWWfkqD3IxsU/HMK1uJTTxxF2llcKSM4dlSdBy0Piag/DndHocqs32kTOwXUw6lkyggYQBXF0uwTv9jVFm1ZjZgSehV3kpx5RTvizZ9MqEI8lotCRvokC9HLI0pGfKtSmlKgCKL+OUoc9QI5HW3wLtYbLersumd4UCKEPk/uWAdKEh4ntSJiW2km8waGFsg/VSNFj5vaDK3LC4PxfsRvi1a2veZW7JUs/VOleE9wwgTH+A/oqPPcyksBY7aQ4TxYjvS9Qj9LtXkvOwttQMgPGwoxlqBEBhR/xLUwmecHkHzgjACFtxE=',
  },
})

const formLabelWidth = ref('120px')
const textarea = ref('')
const vc = ref('')
const recorderbutton = ref(false)
const nlp = ref(false)
const emotion = ref(0)
const action = ref('A_RH_hello_O')
const _volume = ref(100)

// 实例变量
let avatarPlatform2: any = null
let recorder: any = null

// 添加对话列表相关的状态
interface ChatMessage {
  type: 'user' | 'ai'
  content: string
  time: string
}

const chatList = ref<ChatMessage[]>([])

// 添加消息到对话列表
const addMessage = (content: string, type: 'user' | 'ai') => {
  const now = new Date()
  const time = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`
  chatList.value.push({
    type,
    content,
    time,
  })
}

// 方法
const initSDK = () => {
  avatarPlatform2 = new AvatarPlatform()
  if (avatarPlatform2 != null) {
    // open2('实例化SDK成功')
    createRecoder()
  }
}
// 创建录音器
const createRecoder = () => {
  if (avatarPlatform2 != null) {
    recorder = avatarPlatform2.createRecorder({
      analyser: true,
    })
    // 监听录音器
    recorder.on('recoder_audio', () => {
      if (recorder && recorder.byteTimeDomainData) {
        const data = recorder.byteTimeDomainData
        let sum = 0
        for (let i = 0; i < data.length; i++) {
          sum += Math.abs(data[i] - 128)
        }
        // 计算音量
        const _volume = sum / data.length
      }
    })

    open2('创建录音器成功')
    setSDKEvenet()
  } else {
    alert('请实例化SDK实例')
  }
}

const setSDKEvenet = () => {
  if (avatarPlatform2 != null) {
    avatarPlatform2
      .on(SDKEvents.connected, (initResp: any) => {
        console.warn('SDKEvent.connect:initResp:', initResp)
      })
      .on(SDKEvents.stream_start, () => {
        console.warn('stream_start')
      })
      .on(SDKEvents.disconnected, (err: any) => {
        console.warn('SDKEvent.disconnected:', err)
        if (err) {
          console.error('ws link disconnected because of Error')
          console.error(err.code, err.message, err.name, err.stack)
        }
      })
      .on(SDKEvents.nlp, (nlpData: any) => {
        console.warn('语义理解内容nlp:', nlpData)
        if (nlpData && nlpData.content) {
          addMessage(nlpData.content, 'ai') // 添加 AI 回复
        }
      })
      .on(SDKEvents.frame_start, (frame_start: any) => {
        console.warn('推流开始（可以看作一段文本开始播报时间点）frame_start:', frame_start)
      })
      .on(SDKEvents.frame_stop, (frame_stop: any) => {
        console.warn('推流结束（可以看作一段文本结束播报时间点）frame_stop:', frame_stop)
      })
      .on(SDKEvents.error, (error: any) => {
        console.warn('错误信息error:', error)
      })
      .on(SDKEvents.connected, () => {
        console.warn('connected')
      })
      .on(SDKEvents.asr, (asrData: any) => {
        console.warn('语音识别数据asr:', asrData)
      })
      .on(SDKEvents.tts_duration, (ttsData: any) => {
        console.warn('语音合成用时tts：', ttsData)
      })
      .on(SDKEvents.subtitle_info, (subtitleData: any) => {
        console.warn('subtitleData：', subtitleData)
      })
      .on(SDKEvents.action_start, (action_start: any) => {
        console.warn('动作推流开始（可以看作动作开始时间节点）action_start:', action_start)
      })
      .on(SDKEvents.action_stop, (action_stop: any) => {
        console.warn('动作推流结束（可以看作动作结束时间点）action_stop：', action_stop)
      })
    open2('监听SDK事件成功')
    setPlayerEvenet()
  } else {
    alert('请先实例化SDK')
  }
}

const setPlayerEvenet = () => {
  if (avatarPlatform2 != null) {
    const player = avatarPlatform2.createPlayer()
    player
      .on(PlayerEvents.play, () => {
        console.warn('paly')
      })
      .on(PlayerEvents.playing, () => {
        console.warn('playing')
      })
      .on(PlayerEvents.waiting, () => {
        console.warn('waiting')
      })
      .on(PlayerEvents.stop, () => {
        console.warn('stop')
      })
      .on(PlayerEvents.playNotAllowed, () => {
        console.warn(
          'playNotAllowed：触发了游览器限制自动播放策略，播放前必须与游览器产生交互（例如点击页面或者dom组件），触发该事件后调用avatarPlatform2.player.resume()方法来接触限制',
        )
        player.resume()
      })
    open2('监听播放器事件成功')
    SetApiInfo2()
  } else {
    alert('请先实例化SDK')
  }
}

const SetApiInfo2 = () => {
  if (avatarPlatform2 == null) {
    alert('请先实例化SDK')
  } else {
    console.warn('设置setApiInfo')
    const params = {
      appId: form.appid,
      apiKey: form.apikey,
      apiSecret: form.apisecret,
      serverUrl: form.serverurl,
      sceneId: form.sceneid,
    }
    console.warn('初始化SDK信息：', params)
    avatarPlatform2.setApiInfo(params)
    open2('初始化SDK成功')
    SetGlobalParams()
  }
}

const SetGlobalParams = () => {
  if (avatarPlatform2 != null) {
    const params = Object.assign({}, setglobalparamsform) as any
    console.warn('this.setglobalparamsform.stream.alpha', setglobalparamsform.stream.alpha)
    if (setglobalparamsform.enable == false) {
      delete params.background
      delete params.enable
    }
    console.warn('this.setglobalparamsform', setglobalparamsform)
    if (setglobalparamsform.stream.alpha == true) {
      console.warn('设置alpha=1')
      params.stream.alpha = 1
    } else {
      console.warn('设置alpha=0')
      params.stream.alpha = 0
    }
    console.warn('设置的全局变量为：', params)
    avatarPlatform2.setGlobalParams(params)
    open2('设置全局变量成功')
    start()
  } else {
    alert('请先实例化SDK')
  }
}

const start = () => {
  if (avatarPlatform2 != null) {
    avatarPlatform2.start({ wrapper: document.querySelector('#wrapper') }).catch((e: any) => {
      console.error(e.code, e.message, e.name, e.stack)
    })
  } else {
    alert('请先实例化SDK')
  }
}

const writeText = () => {
  if (avatarPlatform2 != null) {
    const text = textarea.value
    if (text != '' && vc.value == '') {
      addMessage(text, 'user') // 添加用户消息
      avatarPlatform2.writeText(text, {
        nlp: nlp.value,
        tts: {
          volume: 100,
        },
      })
    } else if (text != '' && vc.value != '') {
      addMessage(text, 'user') // 添加用户消息
      avatarPlatform2.writeText(text, {
        nlp: nlp.value,
        tts: {
          vcn: vc.value,
          volume: 100,
          emotion: emotion.value,
        },
      })
    } else {
      alert('内容不许为空')
    }
  } else {
    alert('请先实例化SDK')
  }
}

const writeCmd = () => {
  if (avatarPlatform2 != null) {
    avatarPlatform2.writeCmd('action', action.value)
  }
}

const interrupt = () => {
  if (avatarPlatform2 != null) {
    avatarPlatform2.interrupt()
  } else {
    alert('请先实例化SDK')
  }
}

const startRecord = () => {
  if (avatarPlatform2 != null) {
    avatarPlatform2.recorder.startRecord(
      0,
      () => {
        console.warn('STOPED RECORDER')
      },
      {
        nlp: true,
        avatar_dispatch: {
          interactive_mode: 0,
        },
      },
    )
    recorderbutton.value = true
  } else {
    alert('请先实例化SDK')
  }
}

const stopRecord = () => {
  if (avatarPlatform2 != null) {
    avatarPlatform2.recorder.stopRecord()
    recorderbutton.value = false
  } else {
    alert('请先实例化SDK')
  }
}

const stop = () => {
  if (avatarPlatform2 != null) {
    avatarPlatform2.stop()
  } else {
    alert('请先实例化SDK')
  }
}

const destroy = () => {
  if (avatarPlatform2 != null) {
    avatarPlatform2.destroy()
    avatarPlatform2 = null
  } else {
    alert('请先实例化SDK')
  }
}

const open2 = (_text: string) => {
  // eslint-disable-next-line no-console
  console.log(_text)
}

// 生命周期钩子
onMounted(async () => {
  const isAutoplayAllowed = await checkAutoplayPermission()
  if (!isAutoplayAllowed) {
    return alert('自动播放被阻止，请手动点击页面或DOM组件')
  }
  initSDK()
})

onBeforeUnmount(() => {
  if (avatarPlatform2) {
    avatarPlatform2.stop()
  }
})

// 动态虚拟人调节透明度
onMounted(() => {
  if (avatarPlatform2) {
    avatarPlatform2.stop()
  }
  const div = document.getElementById('wrapper')
  const range = document.getElementById('opacityRange')

  if (div && range) {
    range.addEventListener('input', function (this: HTMLInputElement) {
      div.style.opacity = this.value
    })
  }
})
</script>

<style scoped>
* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  border: none;
}

.el-button {
  width: 200px;
  margin: 0;
}

#wrapper {
  width: 100%;
  height: 100%;
}

.error {
  border-block-color: red;
}

.widthclass {
  width: 400px;
}

span {
  color: red;
}

/* 添加对话列表样式 */
.chat-list {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 300px;
  max-height: 500px;
  padding: 10px;
  overflow-y: auto;
  background: rgba(255, 255, 255, 90%);
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 10%);
}

.chat-item {
  padding: 8px;
  margin-bottom: 10px;
  border-radius: 4px;
}

.chat-item.user {
  margin-left: 20px;
  background-color: #e3f2fd;
}

.chat-item.ai {
  margin-right: 20px;
  background-color: #f5f5f5;
}

.chat-content {
  margin-bottom: 4px;
}

.chat-time {
  font-size: 12px;
  color: #999;
  text-align: right;
}
</style>
